package com.ruoyi.workflow.service.impl;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.business.domain.ServiceItem;
import com.ruoyi.business.service.IServiceItemService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.workflow.domain.CarPackageAudit;
import com.ruoyi.workflow.service.IBpmnNodeService;
import com.ruoyi.workflow.service.ICarPackageAuditService;
import com.ruoyi.workflow.service.IDoTaskService;
import com.ruoyi.workflow.vo.CarPackageAuditVo;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.rmi.ServerException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Transactional(rollbackFor = Exception.class)
@Service
public class DoTaskServiceImpl implements IDoTaskService {
    @Autowired
    private TaskService taskService;
    @Autowired
    private ICarPackageAuditService carPackageAuditService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private IBpmnNodeService bpmnNodeService;
    @Autowired
    private IServiceItemService serviceItemService;

    @Override
    public TableDataInfo selectCarPackageAuditList(CarPackageAudit carPackageAudit) {
        //创建返回对象
        TableDataInfo tableDataInfo = new TableDataInfo();
        tableDataInfo.setCode(200);
        tableDataInfo.setMsg("查询成功");
        //根据当前登录的用户获取代办任务数量进行分页
        String username = SecurityUtils.getUsername();
        long count = taskService.createTaskQuery().taskCandidateOrAssigned(username).count();
        tableDataInfo.setTotal(count);
        if (count == 0) {
            tableDataInfo.setRows(Collections.emptyList());
            return tableDataInfo;
        }
        //接收分页查询参数
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        Integer startIndex = (pageNum - 1) * pageSize;
        List<CarPackageAudit> auditList = new ArrayList<>();
        //查询当前用户的任务,一个任务对应一条数据
        List<Task> taskList = taskService.createTaskQuery().taskCandidateOrAssigned(username).listPage(startIndex, pageSize);
        for (Task t : taskList
        ) {
            //查询审核记录--对应一个流程实例
            //基于任务获取流程实例对象
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(t.getProcessInstanceId()).singleResult();
            //基于流程实例对象获取业务标识
            String businessKey = processInstance.getBusinessKey();
            //基于businessKey获取审批记录
            CarPackageAudit audit = carPackageAuditService.getBaseMapper().selectById(businessKey);
            //设置创建人名称
            SysUser sysUser = userService.selectUserById(Long.valueOf(audit.getCreatorId()));
            audit.setCreatorName(sysUser.getUserName());
            //将CarPackageAudit拷贝到vo对象中
            CarPackageAuditVo carPackageAuditVo = new CarPackageAuditVo();
            BeanUtils.copyProperties(audit, carPackageAuditVo);
            //为当前审核记录设置任务ID,名称和候选人名称
            carPackageAuditVo.setTaskId(t.getId());
            carPackageAuditVo.setTaskName(t.getName());
            //通过taskKey查询候选人
            List<SysUser> users = bpmnNodeService.selectUsersByNodeKey(t.getTaskDefinitionKey());
            List<String> usernames = users.stream().map(sysUser1 -> sysUser1.getNickName()).collect(Collectors.toList());
            carPackageAuditVo.setAuditsName(JSON.toJSONString(usernames));
            auditList.add(carPackageAuditVo);
        }

        tableDataInfo.setRows(auditList);

        return tableDataInfo;
    }

    /*审批*/
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void todoAudit(Long id, String taskId, boolean result, String info) throws ServerException {
        //判断是否可审批
        CarPackageAudit carPackageAudit = carPackageAuditService.getBaseMapper().selectById(id);
        if (carPackageAudit.getStatus() != CarPackageAudit.AUDIT_STATUS_INPROGRESS) {
            throw new ServerException("检查审核状态是否合法");
        }
        //校验当前用户是否是当前任务的负责人
        Task task = taskService.createTaskQuery().taskId(taskId).taskCandidateOrAssigned(SecurityUtils.getUsername()).singleResult();
        if (task == null) {
            throw new ServerException("用户不是负责人或任务不存在");
        }
        //完成审批
        taskService.claim(taskId, SecurityUtils.getUsername());//领取任务
        taskService.addComment(taskId, task.getProcessInstanceId(), info);//添加批注
        //流程变量名 == 任务的 key,图中审核同意/拒绝的变量明是任务key
        taskService.setVariable(taskId,task.getTaskDefinitionKey(),result);
        taskService.complete(taskId);//完成审批
        //审批通过
        if (result) {
            //判断是否有下一个节点
            Task nextTask = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            if (nextTask != null) {
                //有为下一个节点设置候选人
                List<SysUser> users = bpmnNodeService.selectUsersByNodeKey(nextTask.getTaskDefinitionKey());
                System.out.println(users);
                for (SysUser u : users) {
                    taskService.addCandidateUser(nextTask.getId(), u.getUserName());
                }
            } else {
                //没有审核流程结束
                //服务项状态更改为审核通过
                serviceItemService.changeStatus(carPackageAudit.getServiceItemId(), ServiceItem.AUDITSTATUS_APPROVED);
                //审核记录中状态更改审核通过
                carPackageAudit.setStatus(CarPackageAudit.AUDIT_STATUS_PASS);
                carPackageAuditService.getBaseMapper().updateById(carPackageAudit);
            }

        } else {
            //审批拒绝
            //将服务项状态更改为重新调整
            serviceItemService.changeStatus(carPackageAudit.getServiceItemId(),ServiceItem.AUDITSTATUS_REPLY);
            //审核记录更新为审核拒绝
            carPackageAudit.setStatus(CarPackageAudit.AUDIT_STATUS_REFUSE);
            carPackageAuditService.getBaseMapper().updateById(carPackageAudit);
            //为下一个任务设置候选人(此时是创建人)
            Task nextTask = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).singleResult();//查询下一个任务
            SysUser sysUser = userService.selectUserById(Long.valueOf(carPackageAudit.getCreatorId()));
            taskService.addCandidateUser(nextTask.getId(),sysUser.getUserName());//设置候选人
        }


    }

    @Override
    public void reapply(Long id, String taskId) throws ServerException {
        //校验
        CarPackageAudit carPackageAudit = carPackageAuditService.getBaseMapper().selectById(id);
        if (carPackageAudit.getStatus()!=CarPackageAudit.AUDIT_STATUS_REFUSE){
            throw new ServiceException("非法操作");
        }
        Task task = taskService.createTaskQuery().taskId(taskId).taskCandidateOrAssigned(SecurityUtils.getUsername()).singleResult();
        if (task==null){
            throw new ServerException("非法操作");
        }
        //开始任务
        taskService.setVariable(taskId,"money",carPackageAudit.getServiceItemPrice().longValue()+"");
        taskService.claim(taskId,SecurityUtils.getUsername());
        taskService.complete(taskId);
        //为下个任务设置候选人
        Task nextTask = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        List<SysUser> users = bpmnNodeService.selectUsersByNodeKey(nextTask.getTaskDefinitionKey());
        for (SysUser u:users
             ) {
            taskService.addCandidateUser(nextTask.getId(),u.getUserName());
        }
        serviceItemService.changeStatus(carPackageAudit.getServiceItemId(), ServiceItem.AUDITSTATUS_AUDITING);
        carPackageAudit.setStatus(CarPackageAudit.AUDIT_STATUS_INPROGRESS);
        carPackageAuditService.getBaseMapper().updateById(carPackageAudit);
    }
}
